iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0

Hello, 各位 iT 邦幫忙 的粉絲們大家好~~~

在本系列文會延續 Re: 從零改用 .NET MAUI 技術來繼續過去用 Xamarin 技術開發的一個 App : TopStore 使用 .NET MAUI 技術所建立的 TopStore App ,更新 .NET MAUI 在 .NET 6 轉換到 .NET 7 時所需要調整的部分,並持續地的開發 TopStore App 其他需要的功能。

本篇是 Re: 從零續用 .NET MAUI 技術開發過去的一個 App : TopStore 系列 系列文的 EP22。


當有 "下訂單" 的狀態進入到 "商品詳細頁面" 時,在頁面右上方的 "ToolbarItem" 就要換成 "加訂單" 的選向來顯示,而原本的 "新增/編輯" 就先隱藏起來。

理論上這樣的功能應該不太困難,但很莫名的是 ToolbarItem 居然沒有 IsVisible 屬性可以進行這樣的調整,而且從 2018 年開始就已經是被標註成要加入的功能,但卻都一直沒有下文,這點著實讓人想不透!

有興趣的人可以參與 GitHub 上的討論 https://github.com/dotnet/maui/issues/3701

話雖如此, ToolbarItem 本身沒有設計這個 IsVisible 屬性,但要自己實作也不是太困難,從上述的 GitHub 連結當中,就已經有大大把處理的方式給寫出來,處理的方式大致上就是繼承原本的 ToolbarItem,再額外賦予一個 IsVisible 屬性,並針對此屬性值去處理此 ToolbarItem 該不該出現在 Page 的 ToolbarItems 當中。

但注意此方式適用於一開始畫面上已經在 XAML 當中,有撰寫設計好的 ToolbarItem,然後根據 IsVisible 的屬性值決定是否留下該 ToolbarItem 元件顯示;如果要動態調整的就需要再透過額外手法處理,GitHub 討論串中也有提及。

由於在目前使用的情境中,大概使用自行設計 IsVisible 屬性給 ToolbarItem 的做法就足以應付了,所以這邊就依樣畫葫蘆並稍微改寫了一下囉~~~

首先,在專案當中加入 CustomControls 資料夾,並在該資料夾當中加入有下列程式碼的類別檔:

namespace TopStoreApp.CustomControls;

internal class BindableToolbarItem : ToolbarItem
{

}

完成結果如下圖:
01

完成後,在該類別當中加入以下設計:

public static readonly BindableProperty IsVisibleProperty =
BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(BindableToolbarItem),
                        true, BindingMode.OneWay, propertyChanged: OnIsVisibleChanged);

public bool IsVisible
{
    get => (bool)GetValue(IsVisibleProperty);
    set => SetValue(IsVisibleProperty, value);
}

private static void OnIsVisibleChanged(BindableObject bindable, object oldvalue, object newvalue)
{
    var item = bindable as BindableToolbarItem;

    item.RefreshVisibility();      
}

private void RefreshVisibility()
{
    if (Parent == null )
    {
        return;
    }
    
    bool value = IsVisible;

    var toolbarItems = ((ContentPage)Parent).ToolbarItems;

    var isExist = toolbarItems.Contains(this);

    if (value)
    {
        Application.Current.Dispatcher.Dispatch(() => { toolbarItems.Add(this); });
    }
    else if (!value && isExist)
    {
        Application.Current.Dispatcher.Dispatch(() => { toolbarItems.Remove(this); });
    }
}

完成結果如下圖:
02

接著再把 Pages 底下的 ProductDetailPage 進行 XAML 的改寫。

首先針對 ContentPage 加入 XAML Namespace 的使用,並幫 ToolbarItems 的內容改寫成使用上述的客製化 BindableToolbarItem。

xmlns:customcontrols="clr-namespace:TopStoreApp.CustomControls"
<customcontrols:BindableToolbarItem 
    Command="{Binding AddOrderCommand}" IsVisible="{Binding IsOrder}" Text="加訂單" />
<customcontrols:BindableToolbarItem 
    IsVisible="{Binding IsOrder, Converter={StaticResource BoolReverseValueConverter}}"
    Command="{Binding SaveCommand}" Text="{Binding IsEdit, Converter={StaticResource DetailPageToolBarItemDisplayText}, ConverterParameter='儲存,編輯'}" />

完成結果如下圖:
03

完成後,若從 "下訂單" 模式的操作進入到 ProductDetailPage 那 ToolbarItems 就會出現 "加訂單"。
結果如下圖:
04_AddOrder

若是直接從 "瀏覽商品" 模式的操作進入到 ProductDetailPage 那 ToolbarItems 就會出現 "編輯/儲存"。
04_Edit/Save

最後到 ProductDetailPageViewModel 當中補上 AddOrder 的方法,但先用 DisplayAlert 代替處理 "加訂單" 的事情:

[RelayCommand]
private async void AddOrder()
{
    await Shell.Current.DisplayAlert("通知", "尚未實作", "OK");
}

完成結果如下圖:
05

執行的結果:
06-Android

下一回就再繼續處理 "加訂單" 的部分囉~~~


上一篇
EP21
下一篇
EP23
系列文
Re: 從零續用 .NET MAUI 技術開發過去的一個 App : TopStore 系列30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言